package com.sunxboy.platform.thread;

import java.lang.Thread.UncaughtExceptionHandler;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;

import org.apache.log4j.Logger;

/**
 * Factory that will create threads with settings like default java thread factory, except ThreadGroup logic and allow
 * to specify a string as part of generated thread name
 */
public class NamedThreadFactory implements ThreadFactory {
    private final static AtomicInteger factoryNo = new AtomicInteger(1);
    private final String namePrefix;
    private final AtomicLong threadNo = new AtomicLong(1);
    private int thisFactoryNo;

    public NamedThreadFactory(String namePrefix) {
        if (namePrefix == null) {
            throw new IllegalArgumentException("Non null thread factory name is required");
        }

        this.namePrefix = namePrefix;
        this.thisFactoryNo = factoryNo.getAndIncrement();
    }

    public Thread newThread(Runnable r) {
        Thread thread = new Thread(r, String.format("%s-f%d-t%d", namePrefix, this.thisFactoryNo, threadNo.getAndIncrement()));

        if (thread.isDaemon()) {
            thread.setDaemon(false);
        }

        if (thread.getPriority() != Thread.NORM_PRIORITY) {
            thread.setPriority(Thread.NORM_PRIORITY);
        }

        thread.setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
            public void uncaughtException(Thread t, Throwable e) {
                Logger threadLogger = Logger.getLogger(t.getClass());
                threadLogger.error("Thread terminated with uncaught exception", e);
            }
        });

        return thread;
    }
}
